#include "board.h"
#include "drv_touch.h"
#include "drv_touch_xpt2046.h"

#if TOUCH_USE_XPT2046

// A/D ͨ��ѡ�������ֺ͹����Ĵ���
#define	CHX 	0xd0 	//ͨ��Y+��ѡ�������	
#define	CHY 	0x90	//ͨ��X+��ѡ�������
//#define	CHX 	0x90 	//ͨ��Y+��ѡ�������	
//#define	CHY 	0xd0	//ͨ��X+��ѡ�������

#define TP_CS(a)	\
						if (a)	\
						GPIOB->BSRR = GPIO_Pin_3;	\
						else		\
						GPIOB->BRR = GPIO_Pin_3
						
#define TP_DCLK(a)	\
						if (a)	\
						GPIOB->BSRR = GPIO_Pin_2;	\
						else		\
						GPIOB->BRR = GPIO_Pin_2
						
#define TP_DIN(a)	\
						if (a)	\
						GPIOB->BSRR = GPIO_Pin_0;	\
						else		\
						GPIOB->BRR = GPIO_Pin_0

#define TP_DOUT		GPIOB->IDR & GPIO_Pin_1

void touch_xpt2046_init(void) 
{
//	GPIOB->CRL&=0XFFFF0000;
//  GPIOB->CRL|=0X00003383;
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

//	
//	TP_CS(0);
}

static void Delayus(int i)
{
	while(--i);
}
//====================================================================================
static void WR_CMD(uint8_t cmd) 
{
	uint8_t buf;
	uint8_t i;
	//TP_CS(0);
	TP_DIN(0);
	TP_DCLK(0);
	//TP_CS(0);
	for(i=0;i<8;i++) 
	{
		buf=(cmd>>(7-i))&0x1;
		TP_DIN(buf);
		Delayus(5);
		TP_DCLK(1);
		Delayus(5);
		TP_DCLK(0);
	}
}
//====================================================================================
static uint16_t RD_AD(void) 
{
	uint16_t buf=0,temp;
	uint8_t i;
	TP_DIN(0);
	TP_DCLK(1);
	for(i=0;i<12;i++) 
	{
		TP_DCLK(0);    
		Delayus(5);      
		temp= (TP_DOUT) ? 1:0;
		buf|=(temp<<(11-i));
		Delayus(5);
		TP_DCLK(1);
		Delayus(5);
	}
	//TP_CS(1);
	buf&=0x0fff;
	return(buf);
}

int touch_get_raw(uint32_t *raw_x,uint32_t *raw_y)
{
	uint32_t avg_x = 0;
	uint32_t avg_y = 0;
	uint8_t nsamples = 0;
	uint8_t i= 0;
	for(; i < 8; i++)
	{
		nsamples++;
		
		WR_CMD(CHX);
		avg_x+= RD_AD();
		
		WR_CMD(CHY);
		avg_y+= RD_AD();
	}
	*raw_y = (avg_x / nsamples);
	*raw_x = (avg_y / nsamples);
	return 1;
}

#include "touch_port.h"
uint32_t touch_x_min = TOUCH_X_MIN;
uint32_t touch_x_max = TOUCH_X_MAX;
uint32_t touch_y_min = TOUCH_Y_MIN;
uint32_t touch_y_max = TOUCH_Y_MAX;
uint32_t touch_dir  = TOUCH_DIR;

void touch_set_calibrate(uint32_t x_min,uint32_t x_max,uint32_t y_min,uint32_t y_max)
{
	touch_x_min = x_min;
	touch_x_max = x_max;
	touch_y_min = y_min;
	touch_y_max = y_max;
}

#include "lcd_port.h"
uint32_t screen_x = LCD_WIDTH;
uint32_t screen_y = LCD_HEIGHT;
uint32_t screen_dir = LCD_DIR;

void touch_set_screen(uint32_t x,uint32_t y,uint32_t dir)
{
	screen_x = x;
	screen_y = y;
	screen_dir = dir;
}

void touch_raw_to_xy(uint32_t raw_x,uint32_t raw_y,uint32_t *x,uint32_t *y)
{
	uint32_t temp = 0;
	
	if(raw_x < touch_x_min) raw_x = touch_x_min;
	if(raw_x > touch_x_max) raw_x = touch_x_max;

	if(raw_y < touch_y_min) raw_y = touch_y_min;
	if(raw_y > touch_y_max) raw_y = touch_y_max;
	
	if(screen_dir)  //swap x y raw
	{
		temp = raw_x;
		raw_x = raw_y;
		raw_y = temp;
	}
	switch(touch_dir)
	{
		case 0:
			*x = (raw_x - touch_x_min) * screen_x / (touch_x_max - touch_x_min);
			*y = (raw_y - touch_y_min) * screen_y / (touch_y_max - touch_y_min);
			break;
		case 1:
			*x = (raw_x - touch_x_min) * screen_x / (touch_x_max - touch_x_min);
			*y = (touch_y_max - raw_y) * screen_y / (touch_y_max - touch_y_min);
			break;
		case 2:
			*x = (touch_x_max - raw_x) * screen_x / (touch_x_max - touch_x_min);
			*y = (touch_y_max - raw_y) * screen_y / (touch_y_max - touch_y_min);
			break;
		case 3:
			*x = (touch_x_max - raw_x) * screen_x / (touch_x_max - touch_x_min);
			*y = (raw_y - touch_y_min) * screen_y / (touch_y_max - touch_y_min);
			break;
	}
}

void touch_get_xy(struct touch_message *msg)
{
	uint32_t raw_x = 0,raw_y = 0;
	
	if(touch_get_raw(&raw_x,&raw_y)>0)
	{
		touch_raw_to_xy(raw_x,raw_y,&msg->x,&msg->y);
		msg->event = TOUCH_EVENT_DOWN;
	}else
	{
		msg->event = TOUCH_EVENT_NONE;
	}
}

#endif
